home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Libraries
/
TurboTCP 1.0.1
/
TurboTCP.source
/
CTelnetInterpreter.cp
< prev
next >
Wrap
Text File
|
1993-11-21
|
12KB
|
648 lines
/*
** CTelnetInterpreter.cp
**
** TurboTCP support library
** Generic Telnet protocol interpreter
**
** Copyright © 1993, FrostByte Design / Eric Scouten
**
*/
#include "CTelnetInterpreter.h"
#include "CTCPDriver.h"
#include "CTCPStream.h"
#include "CTCPResolverCall.h"
// —— initialization ——
/*______________________________________________________________________
**
** ITelnetInterpreter
**
** Initialize the Telnet interpreter session document.
**
** aSupervisor (CApplication *): the document’s supervisor
** printable (Boolean): TRUE if document is printable
** recBufferSize (long): size of the receive buffer we need
** theDefaultPort (b_16): default IP port number
** autoReceiveSize (long): number of entries in RDS for auto-receive,
** 0 to disable autoreceiving
** autoReceiveNum (short): number of auto-receive calls to issue at once
** must be at least 1
**
*/
void CTelnetInterpreter::ITelnetInterpreter (CApplication *aSupervisor, Boolean printable,
long recBufferSize, b_16 theDefaultPort,
short autoReceiveSize, short autoReceiveNum)
{
itsState = normalChar;
CTCPSessionDoc::ITCPSessionDoc(aSupervisor, printable, recBufferSize, theDefaultPort,
TRUE, autoReceiveSize, autoReceiveNum);
showFileName = FALSE;
}
// —— data handling methods ——
/*______________________________________________________________________
**
** HandleDataArrived
**
** Process incoming data.
**
** theData (Ptr): pointer to the block of data
** theDataSize (b_16): size of the data block
** isUrgent (Boolean): TRUE if urgent data
**
*/
void CTelnetInterpreter::HandleDataArrived (Ptr theData, b_16 theDataSize, Boolean isUrgent)
{
uchar theChar;
uchar theLine[83];
short lineIndex;
// parse each character separately
while (theDataSize--) {
theChar = (uchar) (*(theData++));
// respond to current Telnet state
switch (itsState) {
// normal operation: write character
case normalChar:
// optimization: try to grab several chars at once
lineIndex = 0;
while ((theDataSize > 1) && (theChar >= ' ') && (theChar != charIAC)) {
theDataSize++;
theData--;
lineIndex = 0;
while ((theDataSize > 0) && (((uchar) *theData) >= ' ') &&
(*theData != charIAC) && (lineIndex < 80))
theDataSize--, theLine[lineIndex++] = (uchar) *(theData++);
if ((theDataSize > 0) && (*theData == charCR))
theDataSize--, theData++, theLine[lineIndex++] = charCR;
if ((theDataSize > 0) && (*theData == charLF))
theDataSize--, theData++, theLine[lineIndex++] = charLF;
theLine[lineIndex] = '\0';
if (lineIndex)
HandleNVTLine((char *) &theLine[0]);
if (theDataSize < 1)
break;
theChar = (uchar) (*(theData++));
theDataSize--;
}
if ((lineIndex) && !(theDataSize))
break;
// end of loop: test for IAC
if (theChar == charIAC) {
itsState = gotIAC;
if (showDebug)
PrintDebugStr("[IAC");
}
else
HandleNVTChar(theChar);
break;
// received IAC (interpret as command)
case gotIAC:
case gotIACinSB:
ReceivedIAC(theChar);
break;
// handle other cases
case gotSB:
if (theChar == charIAC) {
itsState = gotIACinSB;
if (showDebug)
PrintDebugStr(" IAC");
}
else
ReceivedSB(theChar);
break;
case gotWILL:
if (showDebug)
PrintDebugCharNum(theChar, ' ', ']');
ReceivedWill(theChar);
itsState = normalChar;
break;
case gotWONT:
if (showDebug)
PrintDebugCharNum(theChar, ' ', ']');
ReceivedWont(theChar);
itsState = normalChar;
break;
case gotDO:
if (showDebug)
PrintDebugCharNum(theChar, ' ', ']');
ReceivedDo(theChar);
itsState = normalChar;
break;
case gotDONT:
if (showDebug)
PrintDebugCharNum(theChar, ' ', ']');
ReceivedDont(theChar);
itsState = normalChar;
break;
}
}
}
/*______________________________________________________________________
**
** HandleNVTChar
**
** Process a character which was recieved over Telnet for the network virtual terminal.
**
** theChar (char): the character which was received
**
*/
void CTelnetInterpreter::HandleNVTChar (char theChar)
{
// null method
}
/*______________________________________________________________________
**
** HandleNVTLine
**
** Process a line (or <81 chars) which was recieved over Telnet for the network virtual
** terminal.
**
** theLine (char *): the line which was received (C string)
**
*/
void CTelnetInterpreter::HandleNVTLine (char *theLine)
{
// null method
}
// —— Telnet command handling ——
/*______________________________________________________________________
**
** ReceivedIAC
**
** Respond to a Telnet [IAC command] sequence.
**
** theCommand (uchar): the command code
**
*/
void CTelnetInterpreter::ReceivedIAC (uchar theCommand)
{
// which command is it?
switch (theCommand) {
case escSE:
if (showDebug)
PrintDebugStr(" SE]");
sbBfr[sbBfrIndex] = '\0';
if (itsState == gotIACinSB)
ReceivedSE();
itsState = normalChar;
break;
case escNOP:
if (showDebug)
PrintDebugStr(" NOP]");
itsState = normalChar;
break;
case escDM:
if (showDebug)
PrintDebugStr(" DM]");
ReceivedSynch();
itsState = normalChar;
break;
case escBRK:
if (showDebug)
PrintDebugStr(" BRK]");
ReceivedBRK();
itsState = normalChar;
break;
case escIP:
if (showDebug)
PrintDebugStr(" IP]");
ReceivedIP();
itsState = normalChar;
break;
case escAO:
if (showDebug)
PrintDebugStr(" AO]");
ReceivedAO();
itsState = normalChar;
break;
case escAYT:
if (showDebug)
PrintDebugStr(" AYT]");
ReceivedAYT();
itsState = normalChar;
break;
case escEC:
if (showDebug)
PrintDebugStr(" EC]");
ReceivedEC();
itsState = normalChar;
break;
case escEL:
if (showDebug)
PrintDebugStr(" EL]");
ReceivedEL();
itsState = normalChar;
break;
case escGA:
if (showDebug)
PrintDebugStr(" GA]");
ReceivedGA();
itsState = normalChar;
break;
case escSB:
if (showDebug)
PrintDebugStr(" SB");
itsState = gotSB;
sbBfrIndex = 0;
break;
case escWILL:
if (showDebug)
PrintDebugStr(" WILL");
itsState = gotWILL;
break;
case escWONT:
if (showDebug)
PrintDebugStr(" WONT");
itsState = gotWONT;
break;
case escDO:
if (showDebug)
PrintDebugStr(" DO");
itsState = gotDO;
break;
case escDONT:
if (showDebug)
PrintDebugStr(" DONT");
itsState = gotDONT;
break;
case escIAC:
default:
if (itsState == gotIACinSB) {
ReceivedSB(theCommand);
itsState = gotIAC;
}
else {
if (showDebug)
PrintDebugCharNum(theCommand, '?', ']');
HandleNVTChar(theCommand);
itsState = normalChar;
}
}
}
/*______________________________________________________________________
**
** ReceivedWill
**
** Respond to a Telnet [IAC WILL option] sequence.
**
** theOption (uchar): the option code
**
*/
void CTelnetInterpreter::ReceivedWill (uchar theOption)
{
uchar respondStr[4];
// reject all options
respondStr[0] = charIAC;
respondStr[1] = escWONT;
respondStr[2] = theOption;
respondStr[3] = '\0';
if (showDebug) {
PrintDebugStr("{IAC WONT");
PrintDebugCharNum(theOption, ' ', '}');
}
itsStream->SendCString((char *) &respondStr);
}
/*______________________________________________________________________
**
** ReceivedWont
**
** Respond to a Telnet [IAC WONT option] sequence.
**
** theOption (uchar): the option code
**
*/
void CTelnetInterpreter::ReceivedWont (uchar theOption)
{
// null method
}
/*______________________________________________________________________
**
** ReceivedDo
**
** Respond to a Telnet [IAC DO option] sequence.
**
** theOption (uChar): the option code
**
*/
void CTelnetInterpreter::ReceivedDo (uchar theOption)
{
uchar respondStr[4];
// reject all options
respondStr[0] = charIAC;
respondStr[1] = escWONT;
respondStr[2] = theOption;
respondStr[3] = '\0';
if (showDebug) {
PrintDebugStr("{IAC WONT");
PrintDebugCharNum(theOption, ' ', '}');
}
itsStream->SendCString((char *) &respondStr);
}
/*______________________________________________________________________
**
** ReceivedDont
**
** Respond to a Telnet [IAC DONT option] sequence.
**
** theOption (uchar): the option code
**
*/
void CTelnetInterpreter::ReceivedDont (uchar theOption)
{
// null method
}
/*______________________________________________________________________
**
** ReceivedBRK
**
** Respond to a Telnet [IAC BRK] sequence.
**
*/
void CTelnetInterpreter::ReceivedBRK (void)
{
// null method
}
/*______________________________________________________________________
**
** ReceivedSynch
**
** Respond to a Telnet [Urgent][IAC DM] sequence.
**
*/
void CTelnetInterpreter::ReceivedSynch (void)
{
// null method
}
/*______________________________________________________________________
**
** ReceivedIP
**
** Respond to a Telnet [IAC IP] sequence.
**
*/
void CTelnetInterpreter::ReceivedIP (void)
{
// null method
}
/*______________________________________________________________________
**
** ReceivedAO
**
** Respond to a Telnet [IAC AO] sequence.
**
*/
void CTelnetInterpreter::ReceivedAO (void)
{
// null method
}
/*______________________________________________________________________
**
** ReceivedAYT
**
** Respond to a Telnet [IAC AYT] sequence.
**
*/
void CTelnetInterpreter::ReceivedAYT (void)
{
// null method
}
/*______________________________________________________________________
**
** ReceivedEC
**
** Respond to a Telnet [IAC EC] sequence.
**
*/
void CTelnetInterpreter::ReceivedEC (void)
{
// null method
}
/*______________________________________________________________________
**
** ReceivedEL
**
** Respond to a Telnet [IAC EL] sequence.
**
*/
void CTelnetInterpreter::ReceivedEL (void)
{
// null method
}
/*______________________________________________________________________
**
** ReceivedGA
**
** Respond to a Telnet [IAC GA] sequence.
**
*/
void CTelnetInterpreter::ReceivedGA (void)
{
// null method
}
/*______________________________________________________________________
**
** ReceivedSB
**
** Receive subnegotiation parameters. Buffers characters until SE is received.
**
** theChar (uchar): the latest character
**
*/
void CTelnetInterpreter::ReceivedSB (uchar theChar)
{
if (showDebug)
PrintDebugCharNum(theChar, ' ', '\0');
sbBfr[sbBfrIndex++] = theChar;
}
/*______________________________________________________________________
**
** ReceivedSE
**
** Parse subnegotiation parameters. Called when [IAC SE] is received.
**
*/
void CTelnetInterpreter::ReceivedSE (void)
{
// null method
}
/*______________________________________________________________________
**
** —— debugging methods ——
**
** These methods were useful to me in debugging the implementation of various Telnet
** options. In a terminal-based method (such as MiniTelnet’s CTelnetTerminal), these
** should be hooked up to routines that print the relevant data to the display screen.
**
*/
/*______________________________________________________________________
**
** PrintDebugStr
**
** Write a string to the terminal for debugging purposes.
**
** theDebugStr (char *): the string to write
**
*/
void CTelnetInterpreter::PrintDebugStr (char *theDebugStr)
{
// null method, since no terminal is defined
}
/*______________________________________________________________________
**
** PrintDebugCharNum
**
** Print a character number for debugging. Provided as a debugging routine. The number
** is bracketed by the two characters indicated, i.e. if you call PrintDebugCharNum('!', '[', ']'),
** you get [33] written to the terminal.
**
** theChar (char): the character number to write
** leftBracket (char): prefix to character number
** rightBracket (char): suffix to character number
**
*/
void CTelnetInterpreter::PrintDebugCharNum (char theChar, char leftBracket, char rightBracket)
{
// null method, since no terminal is defined
}